#include "debug_usart.h"

// 中断相关配置
void NVIC_config(void){
    NVIC_InitTypeDef init;

    // NVIC 优先级 组
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    init.NVIC_IRQChannel = DEBUG_USART_IRQn;
    init.NVIC_IRQChannelCmd = ENABLE;
    init.NVIC_IRQChannelPreemptionPriority = 1;
    init.NVIC_IRQChannelSubPriority = 1;

    NVIC_Init(&init);
}

void debug_usart_init(void) {
    GPIO_InitTypeDef GPIO_init;
    USART_InitTypeDef USART_init;

    // 开启 GPIO 时钟
    RCC_AHB1PeriphClockCmd(DEBUG_USART_RX_GPIO_CLK | DEBUG_USART_TX_GPIO_CLK, ENABLE);

    // 开启 USART1 时钟
    RCC_APB2PeriphClockCmd(DEBUG_USART_CLK, ENABLE);

    NVIC_config();

    // 连接 引脚到 串口 / 引脚复用配置
    GPIO_PinAFConfig(DEBUG_USART_RX_GPIO_PORT,
                    DEBUG_USART_RX_SOURCE, DEBUG_USART_RX_AF);

    GPIO_PinAFConfig(DEBUG_USART_TX_GPIO_PORT,
                    DEBUG_USART_TX_SOURCE, DEBUG_USART_TX_AF);

    // 配置 GPIO
    GPIO_init.GPIO_Mode = GPIO_Mode_AF;
    GPIO_init.GPIO_OType = GPIO_OType_PP;
    GPIO_init.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_init.GPIO_Speed =  GPIO_Speed_50MHz;

    // 配置 USART
    USART_init.USART_BaudRate = DEBUG_USART_BAUDRATE;
    // 不使用 硬件流 控制
    USART_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_init.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    // 没有 校验位
    USART_init.USART_Parity = USART_Parity_No;
    // 停止位 1 位
    USART_init.USART_StopBits = USART_StopBits_1;
    // 数据长度 8 bit
    USART_init.USART_WordLength = USART_WordLength_8b;
    

    GPIO_init.GPIO_Pin = DEBUG_USART_RX_PIN;
    GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_init);

    GPIO_init.GPIO_Pin = DEBUG_USART_TX_PIN;
    GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_init);

    USART_Init(DEBUG_USART, &USART_init);

    // USART 中断配置
    USART_ITConfig(DEBUG_USART, USART_IT_RXNE, ENABLE);
		USART_ITConfig(DEBUG_USART, USART_IT_IDLE, ENABLE);
    // 使能串口
    USART_Cmd(DEBUG_USART, ENABLE);


}

// 发送 单个数据
void sendCh(USART_TypeDef *USARTx, char ch) {
    USART_SendData(USARTx, ch);
    // 等待 TDR  为空
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}

// 发送 数据
void sendData(USART_TypeDef *USARTx, char *str) {
    while((*str) != '\0') {
        sendCh(USARTx, *str);
        str++;
    }
    // 等待 发送 完成
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);
}


__attribute((weak))  void usart_recv_handler(uint8_t *buff, uint16_t count) {}

#define DEBUG_USART_RECV_SIZE 	256
uint8_t recv_buff[DEBUG_USART_RECV_SIZE];
uint16_t count = 0;

// USART 接收 中断
void DEBUG_USART_IRQHandler(void) {

    if(USART_GetITStatus(DEBUG_USART, USART_IT_RXNE) == SET) {
			uint8_t temp = USART_ReceiveData(DEBUG_USART);
			recv_buff[count++] = temp;
			if(count >= DEBUG_USART_RECV_SIZE) {
				count = 0;
			}
    }
		
		if(USART_GetITStatus(DEBUG_USART, USART_IT_IDLE) == SET) {
			USART_ReceiveData(DEBUG_USART);
			recv_buff[count] = '\0';
			usart_recv_handler(recv_buff, count);
			count = 0;	
		}

}

void send_str_len(USART_TypeDef *USARTx, uint8_t *str, uint8_t len){
	
	for(uint8_t i = 0; i < len; i++){
		sendCh(USARTx, (char)str[i]);
	}
}

// 将串口 重定向到 printf
int fputc(int ch, FILE *f) {
	USART_SendData(DEBUG_USART, (uint8_t)ch);
	while(USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);
	return ch;
}

int fgetc(FILE *f){
	while(USART_GetFlagStatus(DEBUG_USART, USART_FLAG_RXNE) == RESET);
	
	return USART_ReceiveData(DEBUG_USART);
}



